#include "POSIX_MessageQueue.hpp"
#include <fcntl.h>
#include <sys/stat.h>
#include <stdexcept>

POSIX_MessageQueue::POSIX_MessageQueue(const std::string & name)
{
  id=mq_open(name.c_str(),O_EXCL | O_RDWR,S_IWUSR | S_IRUSR,nullptr);
  if(id==-1)
    throw std::runtime_error("无法打开POSIX消息队列");
  struct mq_attr attr;
  if(mq_getattr(id,&attr)==-1)
    throw std::runtime_error("无法获取POSIX消息队列属性");
  ReceiveMessageSize=attr.mq_msgsize;
  ReceiveMessageBuffer=new char[attr.mq_msgsize];
  threadID=pthread_self();
}

POSIX_MessageQueue::~POSIX_MessageQueue()
{
  if(pthread_equal(pthread_self(),threadID)==0)
    pthread_cancel(threadID);
  if(receiveThread.joinable())
    receiveThread.join();
  mq_close(id);
}

std::string POSIX_MessageQueue::ReceiveData()
{
  ssize_t recSize=mq_receive(id,ReceiveMessageBuffer,ReceiveMessageSize,nullptr);
  if(recSize==-1)
    throw std::runtime_error("无法从消息队列中获取数据");
  else if(recSize==0)
    return std::string();
  else if(ReceiveMessageBuffer[recSize-1]=='\0')
    recSize--;
  return std::string(ReceiveMessageBuffer,recSize);
}

void POSIX_MessageQueue::SendData(const std::string & val)
{
  if(mq_send(id,val.c_str(),val.length()+1,0)==-1)
    throw std::runtime_error("无法在消息队列中发送消息");
}

void POSIX_MessageQueue::BootActiveReceive(std::function<void(std::string)> func)
{
  ReceiveDataCallback=func;
  receiveThread=std::jthread(&POSIX_MessageQueue::ReceiveFunc,this);
}

void ThreadHandle_SIGINT(int)
{

}

void POSIX_MessageQueue::ReceiveFunc(std::stop_token token)
{
  threadID=pthread_self();
  while(!token.stop_requested())
  {
    ReceiveDataCallback(ReceiveData());
  }
}
